package com.example.docmanagement.entity;

import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.JdbcTypeCode;
import org.hibernate.type.SqlTypes;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.UUID;

/**
 * 用户实体类
 * 对应数据库表：users
 * 实现 UserDetails 接口以支持 Spring Security
 */
@Entity
@Table(name = "users")
@EntityListeners(AuditingEntityListener.class)
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User implements UserDetails {

    /**
     * 用户 ID（UUID）
     */
    @Id
    @GeneratedValue(strategy = GenerationType.UUID)
    private UUID id;

    /**
     * 邮箱（唯一）
     */
    @Column(unique = true, nullable = false, length = 255)
    private String email;

    /**
     * 用户名（唯一）
     */
    @Column(unique = true, nullable = false, length = 100)
    private String username;

    /**
     * 加密后的密码
     */
    @Column(name = "encrypted_password", nullable = false, length = 255)
    private String encryptedPassword;

    /**
     * 全名
     */
    @Column(name = "full_name", length = 255)
    private String fullName;

    /**
     * 头像 URL
     */
    @Column(name = "avatar_url", columnDefinition = "TEXT")
    private String avatarUrl;

    /**
     * 个人简介
     */
    @Column(columnDefinition = "TEXT")
    private String bio;

    /**
     * 手机号
     */
    @Column(length = 20)
    private String phone;

    /**
     * 角色 ID（外键）
     */
    @Column(name = "role_id")
    private Long roleId;

    /**
     * 角色关联（多对一）
     */
    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "role_id", insertable = false, updatable = false)
    private Role role;

    /**
     * 用户状态：active, inactive, banned
     */
    @Column(length = 20)
    private String status;

    /**
     * 邮箱是否已验证
     */
    @Column(name = "email_verified")
    private Boolean emailVerified;

    /**
     * 邮箱验证时间
     */
    @Column(name = "email_confirmed_at")
    private LocalDateTime emailConfirmedAt;

    /**
     * 原始应用元数据（兼容 Supabase）
     */
    @JdbcTypeCode(SqlTypes.JSON)
    @Column(name = "raw_app_meta_data", columnDefinition = "jsonb")
    private String rawAppMetaData;

    /**
     * 原始用户元数据（兼容 Supabase）
     */
    @JdbcTypeCode(SqlTypes.JSON)
    @Column(name = "raw_user_meta_data", columnDefinition = "jsonb")
    private String rawUserMetaData;

    /**
     * 最后登录时间
     */
    @Column(name = "last_sign_in_at")
    private LocalDateTime lastSignInAt;

    /**
     * 最后登录 IP
     */
    @JdbcTypeCode(SqlTypes.INET)
    @Column(name = "last_sign_in_ip", columnDefinition = "inet")
    private String lastSignInIp;

    /**
     * 登录次数
     */
    @Column(name = "sign_in_count")
    private Integer signInCount;

    /**
     * 密码重置令牌
     */
    @Column(name = "reset_token", length = 255)
    private String resetToken;

    /**
     * 密码重置令牌过期时间
     */
    @Column(name = "reset_token_expires_at")
    private LocalDateTime resetTokenExpiresAt;

    /**
     * 软删除时间
     */
    @Column(name = "deleted_at")
    private LocalDateTime deletedAt;

    /**
     * 创建时间（自动填充）
     */
    @CreatedDate
    @Column(name = "created_at", nullable = false, updatable = false)
    private LocalDateTime createdAt;

    /**
     * 更新时间（自动填充）
     */
    @LastModifiedDate
    @Column(name = "updated_at", nullable = false)
    private LocalDateTime updatedAt;

    // ========== UserDetails 接口实现 ==========

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        List<GrantedAuthority> authorities = new ArrayList<>();
        if (role != null && role.getName() != null) {
            authorities.add(new SimpleGrantedAuthority("ROLE_" + role.getName().toUpperCase()));
            if (role.getPermissions() != null) {
                role.getPermissions().forEach(permission ->
                        authorities.add(new SimpleGrantedAuthority(permission.getName()))
                );
            }
        } else {
            authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
        }
        return authorities;
    }

    @Override
    public String getPassword() {
        return encryptedPassword;
    }

    @Override
    public String getUsername() {
        return username;
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return !"banned".equals(status);
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return "active".equals(status) && deletedAt == null;
    }

    /**
     * 持久化之前的回调
     */
    @PrePersist
    public void prePersist() {
        if (this.id == null) {
            this.id = UUID.randomUUID();
        }
        if (this.createdAt == null) {
            this.createdAt = LocalDateTime.now();
        }
        if (this.updatedAt == null) {
            this.updatedAt = LocalDateTime.now();
        }
    }

    /**
     * 更新之前的回调
     */
    @PreUpdate
    public void preUpdate() {
        this.updatedAt = LocalDateTime.now();
    }
}
